package servidor.atacado;

import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Random;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import atacado.IntAtacado;
import basedados.entidades.HistoricoCompras;
import basedados.entidades.HistoricoConfiabilidade;
import basedados.entidades.Produtos;

/**
 * Servidor de Encomendas
 * @author Emerson Shigueo Sugimoto
 * */
public class ServidorAtacado extends UnicastRemoteObject implements IntAtacado {
	private static final long serialVersionUID = 1L;
	private int _porta;
	private JTextArea _txtMensagensServidor;
	private JTextField _txtCaixa;
	private double _confiabilidade;
	private String _nomeServico;
	
	private IniciaServidorAtacado _thInicio;
	
	public void setTxtCaixa(JTextField txtCaixa) {this._txtCaixa = txtCaixa;}
	public JTextField getTxtCaixa() {return _txtCaixa;}
	public int getPorta() { return _porta; }
	public void setPorta(int porta) { this._porta = porta; }
	public JTextArea getTxtMensagensServidor() { return _txtMensagensServidor; }
	public void setTxtMensagensServidor(JTextArea txtMensagensServidor) { this._txtMensagensServidor = txtMensagensServidor; }
	public String getNomeServico() { return _nomeServico; }
	public void setNomeServico(String nomeServico) { this._nomeServico = nomeServico; }
	
	//1099 porta default
	public ServidorAtacado() throws RemoteException {setPorta(1099);setNomeServico("Livraria1");}
	public ServidorAtacado(int porta, String NomeServico, 
			JTextArea jta, 
			double Confiabilidade, JTextField txtCaixa) 
			throws RemoteException {
		setPorta(porta); 
		setTxtMensagensServidor(jta);
		setNomeServico(NomeServico);
		_confiabilidade = Confiabilidade;
		setTxtCaixa(txtCaixa);
	}

	/**
	 * inicia o servidor<br />
	 * cria um thread para isto
	 * */
	public void iniciar() throws RemoteException {
		//printMensagens("Iniciando servidor Atacado: " + getNomeServico());
		parar();
		_thInicio = new IniciaServidorAtacado(getPorta(), getNomeServico(), getTxtMensagensServidor()); 
		_thInicio.start();
	}

	/**
	 * para o servidor
	 * */
	@SuppressWarnings("deprecation")
	public void parar(){
		if (_thInicio != null) {
			_thInicio.stopServer();
			_thInicio.stop();
		}
		_thInicio = null;
	}
	
	/**
	 * imprime mensagens no console ou envia para um JTextArea
	 * */
	private void printMensagens(String msg){
		if (getTxtMensagensServidor() != null) {
			getTxtMensagensServidor().setText(msg + "\n" + getTxtMensagensServidor().getText());
		} else {
			System.out.println(msg);
		}
	}
	
	/**
	 * @idProduto id do produto
	 * @return preco de um produto
	 * */
	@Override
	public double getPrecoProduto(int idProduto) throws RemoteException {
		if (idProduto <= 0) return -1.0;
		
		printMensagens("Servidor retornando preco de produto - " + idProduto );

		//printMensagens("Servidor retorno eh: " + p.getValor());
		return getProduto(idProduto).getValor();
	}
	
    /**
     * @nome nome da empresa
     * @return reputacao de uma loja
     * */
	@Override
	public double getReputacaoLoja(String nome) throws RemoteException {
		double nSucessos = new HistoricoCompras().getTotalSucessosNomeEmpresa(nome);
		double nFalhas = new HistoricoConfiabilidade().getTotalFalhasNomeEmpresa(nome);
		
//		System.out.println("nSucessos: " + nSucessos);
//		System.out.println("nFalhas: " + nFalhas);
//		System.out.println("nSucessos + nFalhas: " + (nSucessos + nFalhas));
//		System.out.println("rt: " + (nSucessos / (nSucessos + nFalhas)));
		
		//se nao tem dados retorna 1
		if ((nSucessos + nFalhas) == 0) return 1;
		
		//retorna o numero de sucessos pelo total
		return (nSucessos / (nSucessos + nFalhas));
	}
	
    /**
     * Atende o pedido de compra de acordo com um grau de confiabilidade
     * @id id do produto
     * @quantidade quantidade a ser comprada do produto
     * @return se o pedido de compra sera atendido ou nao
     * */
	@Override
	public boolean comprar(int id, int quantidade) throws RemoteException {
		double confiabilidade = 95.0;
		if (_confiabilidade>0){confiabilidade=_confiabilidade;}
		
		printMensagens("Confiabilidade: " + confiabilidade);
		
		//sorteia um numero entre 0 a100, se cair entre 0 e confiabilidade, atende a requisicao
		//caso contrario da o bolo, return false
		
		Random random = new Random();
		int numeroGerado = random.nextInt(100); System.out.println("numeroGerado: " + numeroGerado);
		if (numeroGerado > confiabilidade) { //se passou a confiabilidade da o bolo
			printMensagens("dando o bolo para confiabilidade: " + confiabilidade);
			return false;
		}
		
		double vlrCompra = getProduto(id).getValor()*quantidade;
		double caixa = 0.0;
		if (getTxtCaixa() != null) {
			caixa = Double.valueOf(getTxtCaixa().getText());
			getTxtCaixa().setText(String.valueOf(caixa - vlrCompra));
		}
		printMensagens("vlrCompra: " + vlrCompra);
		return true; //atende
	}

    /**
     * @id id do produto
     * @return a quantidade em estoque
     * */
	@Override
	public int getDisponibilidade(int id) {
		if (id <= 0) return 0;
		
		printMensagens("Servidor retornando a quantidade do produto " + id);
		return getProduto(id).getQuantidade();
	}
	
	/**
	 * @return retorna um produto pelo id
	 * */
	private Produtos getProduto(int idProduto){
		return Produtos.getProduto(idProduto);
	}
	
}

/**
 * Thread que inicia o servidor de atacado
 * @author Emerson Shigueo Sugimoto
 * */
class IniciaServidorAtacado extends Thread{
	private int _porta;
	private JTextArea _jta;
	private String _nomeServico;
	private IntAtacado _stub;
	private Registry _registry;
	
	public IniciaServidorAtacado(int porta, String nomeServico, JTextArea jta){
		//para setar o ip real
		//System.setProperty("java.rmi.server.hostname", "192.168.100.198");
		
		_porta = porta;
		_nomeServico = nomeServico;
		_jta = jta;
	}
	
	public void stopServer(){
		try {
			if (_registry!=null) { _registry.unbind(_nomeServico); }
		} catch (AccessException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); }
		_registry = null;
		_stub = null;
	}
	
	public void run(){
		try {
			_stub = new ServidorAtacado();
			_registry = LocateRegistry.createRegistry(_porta); /* porta */
			_registry.bind(_nomeServico, _stub);
			
//			String[] v = _registry.list();
//			for (int i = 0; i < v.length; i++){
//				System.out.println("_registry.list(): " + v[i]);
//			}
//			System.out.println("_registry.lookup: " + _registry.lookup("Livraria1"));
			
			printMensagens("Servidor Atacado iniciado ["+_nomeServico+":"+_porta+"]...");
		} catch (Exception ex) {
			System.err.println(ex.getMessage());
		}
	}
	
	/**
	 * imprime mensagens no console ou envia para um JTextArea
	 * */
	private void printMensagens(String msg){
		if (_jta != null) {
			_jta.setText(msg + "\n" + _jta.getText());
		} else {
			System.out.println(msg);
		}
	}
	
}